package yxy.game.pm2.module.battle;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import yxy.apple.util.concurrent.ThreadPoolManager;
import yxy.apple.util.redisson.RedisException;
import yxy.cherry.battle.Battle;
import yxy.cherry.battle.BattleFomula;
import yxy.cherry.battle.Fighter;
import yxy.cherry.battle.Team;
import yxy.cherry.battle.module.Camp;
import yxy.cherry.battle.module.Position;
import yxy.cherry.battle.module.PropertyData;
import yxy.cherry.battle.module.PropertyType;
import yxy.cherry.battle.module.record.FighterPosition;
import yxy.cherry.battle.module.record.FighterSide;
import yxy.cherry.battle.module.record.result.StatisticFighter;
import yxy.cherry.data.DataCenter;
import yxy.cherry.data.bean.*;
import yxy.game.pm2.bean.Format;
import yxy.game.pm2.bean.Format.FormatType;
import yxy.game.pm2.bean.Hero;
import yxy.game.pm2.bean.PlayerBean;
import yxy.game.pm2.bean.Soul;
import yxy.game.pm2.bean.reset.BattleClear;
import yxy.game.pm2.bean.reset.MapReset;
import yxy.game.pm2.message.BattleMessage;
import yxy.game.pm2.module.NotificationHandle;
import yxy.game.pm2.module.conquest.ConquestModule;
import yxy.game.pm2.module.godBeast.GodBeast;
import yxy.game.pm2.module.godBeast.PickedGodBeastModule;
import yxy.game.pm2.module.hero.FormatHandle;
import yxy.game.pm2.module.niubee.NiuBeeModule;
import yxy.game.pm2.module.playtype.PlayTypeModule;
import yxy.game.pm2.module.soloride.SoloRideModule;
import yxy.game.pm2.module.tower.TowerModule;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.Map.Entry;

import static yxy.cherry.battle.Battle.battleLogger;

public class BattleHandle {

    /**
     * 战斗回合数默认上限：20
     */
    static public int defaultBattleRoundLimit = 20;
    static public int 神兵铸魂升级攻击属性提升 = 200;
    static public int 神兵铸魂升级生命属性提升 = 2000;
    static public int 神兵铸魂升级防御属性提升 = 120;

    static final private int[] 星级对应的怪物属性削减百分比 = {0, 0, 0, 0, 0, 0, 0, 417, 1251, 2085, 2919, 4169, 5419, 6836, 8336, 10003, 12087, 14171, 16255, 18339, 20423};

    /**
     * 玩家的队伍
     */
    public TeamModule teamPlayer(String playerCode, FormatType formatType) {
        FormatHandle formatHandle = new FormatHandle();
        Format format = formatHandle.get(playerCode, formatType);
        return teamPlayer(playerCode, format);
    }

    /**
     * 玩家的队伍
     */
    public TeamModule teamPlayer(String playerCode, Format format) {
        TeamModule team = new TeamModule();
        FormatHandle formatHandle = new FormatHandle();
        Map<Position, Hero> formatHeros = formatHandle.formatHeros(playerCode, format);
        Set<Entry<Position, Hero>> entrySet = formatHeros.entrySet();

        // 武将
        for (Entry<Position, Hero> entry : entrySet) {
            Position position = entry.getKey();
            Hero hero = entry.getValue();

            FighterModule fighterModule = fighter(playerCode, hero, format);

            team.addfighter(position, fighterModule);
        }

        // 神器
        NiuBeeModule niubee = NiuBeeModule.get(playerCode);
        WeaponModule weapon = WeaponModule.create(format.getNb(), niubee.getLevel(), niubee.getRefineLevel(), niubee.getSoulLevel(), niubee.getSkillLevel());
        team.setWeapon(weapon);

        //神兽
        PickedGodBeastModule godBeastModule = PickedGodBeastModule.get(playerCode);
        for (GodBeast godBeast : godBeastModule.getGbs().values()) {
            //选择上阵的那只
            if (godBeast.isBattle() && godBeast.getSkillLevel() > 0) {
                PokemonMoudle therion = new PokemonMoudle();
                Map<String, therionskill> allData = DataCenter.getAllData(therionskill.class);
                therionskill target = null;
                for (therionskill therionskill : allData.values()) {
                    if (therionskill.getType() == godBeast.getType() && therionskill.getLevel() == godBeast.getSkillLevel()) {
                        target = therionskill;
                        break;
                    }
                }
                therion.setId(godBeast.getCode());
                therion.setSkillGroupId(target.getSkillid()[0]);//主动技能
                team.setPokemonMoudle(therion);
                break;
            }
        }

        // 信息
        PlayerBean playerBean = PlayerBean.get(playerCode);
        team.setName(playerBean.getName());
        team.setHead(playerBean.getHead());
        team.setLevel(playerBean.getLevel());
        team.setPower(playerBean.getPower());
        team.setPlayerCode(playerCode);
        return team;
    }

    public FighterModule fighter(String playerCode, Hero hero, Format format) {
        FighterModule fighterModule = FighterModule.create(hero.getDataId(), hero.getLevel(), hero.getStage(), hero.getStar(), 0);

        //初次初始化，后续从缓存获取
        if (hero.getPropertyModule() == null) {
            calculatePower(playerCode, hero, format);
        }

        JSONObject propertyModuleJson = hero.getPropertyModule();
        PropertyModule propertyModule = JSON.parseObject(propertyModuleJson.toString(), new TypeReference<PropertyModule>() {
        });

        fighterModule.setProperty(propertyModule);

        Set<String> skills = new HashSet<>();
        // 魂玉技能
        addSoulSkills(playerCode, hero.getSoulA(), skills);
        addSoulSkills(playerCode, hero.getSoulB(), skills);
        // 兵法技能
        addMagicSkill(playerCode, hero.getMagicA(), skills);
        addMagicSkill(playerCode, hero.getMagicB(), skills);
        addMagicSkill(playerCode, hero.getMagicC(), skills);

        // 重组技能
        ArrayList<String> skillList = refactorSkills(skills);
        fighterModule.setSkills(skillList);
        return fighterModule;
    }

    private ArrayList<String> refactorSkills(Collection<String> skills) {
        ArrayList<String> list = new ArrayList<>();
        for (String skillId : skills) {
            boolean drop = false;
            skillgroup data = DataCenter.getData(skillId, skillgroup.class);
            while (data.getUpid() > 0) {
                skillgroup updata = DataCenter.getData(data.getUpid(), skillgroup.class);
                if (updata == null) {
                    break;
                }
                if (skills.contains(updata.getCode())) {
                    drop = true;
                    break;
                }
                data = updata;
            }
            if (drop) {
                continue;
            }
            list.add(skillId);
        }
        return list;
    }

    private void addSoulSkills(String playerCode, String soulCode, Set<String> skills) {
        try {
            if (soulCode != null) {
                Soul soul = Soul.get(playerCode, soulCode);
                for (Integer skillId : soul.getSkillIds()) {
                    skills.add(String.valueOf(skillId));
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void addMagicSkill(String playerCode, String magicCode, Set<String> skills) {
        try {
            if (magicCode != null) {
                magicdata _magicdata = DataCenter.getData(magicCode, magicdata.class);
                skills.add(String.valueOf(_magicdata.getSkillid()));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 发起战斗 三消前
     */
    public BattleMessage.BattleResponse battleResponse(BattleModule module) {
        BattleMessage.BattleResponse.Builder builder = BattleMessage.BattleResponse.newBuilder();

        // 封装阵容
        for (Entry<Position, FighterModule> entry : module.getTeamA().fighters().entrySet()) {
            builder.addFormat(fighterInfo(entry.getValue(), entry.getKey(), true));
        }
        for (Entry<Position, FighterModule> entry : module.getTeamB().fighters().entrySet()) {
            builder.addFormat(fighterInfo(entry.getValue(), entry.getKey(), false));
        }
        if (module.getTeamA().getWeapon() != null) {
            builder.addFormat(niubeeInfo(module.getTeamA().getWeapon(), true));
        }
        if (module.getTeamB().getWeapon() != null) {
            builder.addFormat(niubeeInfo(module.getTeamB().getWeapon(), false));
        }
        if (module.getTeamA().getPokemonMoudle() != null) {
            builder.addFormat(therionInfo(module.getTeamA().getPokemonMoudle(), true));
        }
        if (module.getTeamB().getPokemonMoudle() != null) {
            builder.addFormat(therionInfo(module.getTeamB().getPokemonMoudle(), false));
        }
        // 玩家信息 左
        builder.addPlayerInfo(playerBattleInfo(module.getTeamA(), true));
        // 玩家信息 右
        builder.addPlayerInfo(playerBattleInfo(module.getTeamB(), false));

        return builder.build();
    }

    /**
     * 三消结束 战斗执行
     */
    public BattleMessage.BattleExecuteResponse battleResponseExecute(BattleModule module, BattleMessage.BattleExecuteRequest request) throws Exception {
        return battleResponseExecute(module, defaultBattleRoundLimit, true, request);
    }

    public BattleMessage.BattleExecuteResponse battleResponseExecute(BattleModule module, int[] angersTeamA, int[] angersTeamB) {
        return battleResponseExecute(module, defaultBattleRoundLimit, true, angersTeamA, angersTeamB);
    }

    /**
     * 三消结束 战斗执行
     */
    public BattleMessage.BattleExecuteResponse battleResponseExecute(BattleModule module, int roundLimit, boolean save,
                                                                     BattleMessage.BattleExecuteRequest request) throws Exception {

        int[] angersTeamA = null;
        int[] angersTeamB = null;
        if (request != null) {
            List<BattleMessage.FighterInfo> fighterInfos = request.getFormatList();
            angersTeamA = angersFromFormatList(fighterInfos, FighterSide.LEFT);
//			angersTeamB = angersFromFormatList(fighterInfos, FighterSide.RIGHT);
        }

        return battleResponseExecute(module, roundLimit, save, angersTeamA, angersTeamB);
    }

    /**
     * 三消结束 战斗执行
     */
    public BattleMessage.BattleExecuteResponse battleResponseExecute(BattleModule module, int roundLimit, boolean save, int[] angersTeamA, int[] angersTeamB) {
        module.getTeamA().initAngers(angersTeamA);
        module.getTeamB().initAngers(angersTeamB);

        BattleMessage.BattleExecuteResponse.Builder builder = BattleMessage.BattleExecuteResponse.newBuilder();

        Team team_a = module.getTeamA().team(true);
        Team team_b = module.getTeamB().team(false);
        team_a.setTeam对手(team_b);
        team_b.setTeam对手(team_a);

        battleExecute(module, team_a, team_b, roundLimit);

        if (save) {
            module.set(1);
        }

        builder.setPlayback(playback(module));// , team_a, team_b));
        Battle.battleLogger(1, module.getRecord());//打印录像

        return builder.build();
    }

    public int[] angersFromFormatList(List<BattleMessage.FighterInfo> fighterInfos, FighterSide fighterSide) {
        int[] angers = new int[7];
        for (BattleMessage.FighterInfo fighterInfo : fighterInfos) {
            FighterPosition fp = FighterPosition.forNumber(fighterInfo.getPosition().getNumber());
            if (fp.getSide().equals(fighterSide)) {
                if (fp.equals(FighterPosition.NBL) || fp.equals(FighterPosition.NBR)) {
                    angers[0] = fighterInfo.getAnger();
                    continue;
                }
                if (fp.equals(FighterPosition.SSL) || fp.equals(FighterPosition.SSR)) {
                    continue;
                }
                angers[fp.getPosition().getValue()] = fighterInfo.getAnger();
            }
        }
        return angers;
    }

    public int[] angersFromFormatList(List<BattleMessage.FighterInfo> fighterInfos) {
        int[] angers = new int[7];
        for (BattleMessage.FighterInfo fighterInfo : fighterInfos) {
            FighterPosition fp = FighterPosition.forNumber(fighterInfo.getPosition().getNumber());
            if (fp.equals(FighterPosition.NBL) || fp.equals(FighterPosition.NBR)) {
                angers[0] = fighterInfo.getAnger();
                continue;
            }

            if (fp.equals(FighterPosition.SSL) || fp.equals(FighterPosition.SSR)) {
                angers[0] = fighterInfo.getAnger();
                continue;
            }
            angers[fp.getPosition().getValue()] = fighterInfo.getAnger();
        }
        return angers;
    }

    public void battleExecute(BattleModule module, Team team_a, Team team_b, int roundLimit) {
        battleLogger(1, "----------------------------战斗开始-----------------------------");
        Date date = new Date();
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String startTime = dateFormat.format(date);
        ConquestModule conquestModule = ConquestModule.get(module.getPlayerCode());
        battleLogger(1, "startTime:::::" + startTime + ":::::playCode:::::" + module.getPlayerCode() + ":::::mapId:::::" + conquestModule.getMapId());
        Battle battle = new Battle();
        battle.battle(team_a, team_b, roundLimit);
        module.setRecord(battle.get记录().streamInfo());
        module.setStatistics(battle.get记录().get统计().getFighters());
        module.setBattleResult(battle.get记录().getResult());
        module.setBattleDetailResult(battle.get记录().getDetailResult());
        module.setRound(battle.getContext().getRound());
        module.setFinished(true);
        module.setStep(battle.get记录().getStep());
        module.timeline().setStartTime(DateTime.now());
        module.time();

    }

    /**
     * 封装武将信息
     */
    private BattleMessage.FighterInfo fighterInfo(FighterModule fighter, Position position, boolean isLeft) {
        BattleMessage.FighterInfo.Builder fighterBuilder = BattleMessage.FighterInfo.newBuilder();
        fighterBuilder.setPosition(BattleMessage.Position.forNumber(FighterPosition.forPosition(position, isLeft).getNumber()));
        fighterBuilder.setDataId(fighter.getHeroId());
        fighterBuilder.setAnger(fighter.getAnger());
        fighterBuilder.setHpc(fighter.hp());
        fighterBuilder.setHpu(fighter.life());
        fighterBuilder.setLevel(fighter.getLevel());
        fighterBuilder.setStar(fighter.getStarlv());
        return fighterBuilder.build();
    }

    /**
     * 封装神器信息
     */
    private BattleMessage.FighterInfo niubeeInfo(WeaponModule niuBee, boolean isLeft) {
        FighterPosition position = isLeft ? FighterPosition.NBL : FighterPosition.NBR;
        BattleMessage.FighterInfo.Builder fighterBuilder = BattleMessage.FighterInfo.newBuilder();
        fighterBuilder.setPosition(BattleMessage.Position.forNumber(position.getNumber()));
        fighterBuilder.setDataId(niuBee.getWeaponId());
        fighterBuilder.setAnger(niuBee.getAnger());
        return fighterBuilder.build();
    }

    /**
     * 封装神器信息
     */
    private BattleMessage.FighterInfo therionInfo(PokemonMoudle pokemonMoudle, boolean isLeft) {
        FighterPosition position = isLeft ? FighterPosition.SSL : FighterPosition.SSR;
        BattleMessage.FighterInfo.Builder fighterBuilder = BattleMessage.FighterInfo.newBuilder();
        fighterBuilder.setPosition(BattleMessage.Position.forNumber(position.getNumber()));
        fighterBuilder.setDataId(pokemonMoudle.getId());
        fighterBuilder.setAnger(pokemonMoudle.getAnger());
        return fighterBuilder.build();
    }


    /**
     * 封装玩家信息
     */
    private BattleMessage.PlayerBattleInfo playerBattleInfo(TeamModule team, boolean left) {
        BattleMessage.PlayerBattleInfo.Builder playerInfo = BattleMessage.PlayerBattleInfo.newBuilder();
        playerInfo.setDir(left ? "L" : "R");
        playerInfo.setName(team.getName());
        playerInfo.setHead(team.getHead());
        playerInfo.setPower(team.getPower());
        return playerInfo.build();
    }

    public BattleMessage.BattlePlayBack playback(BattleRecord module) {
        BattleMessage.BattlePlayBack.Builder builder = BattleMessage.BattlePlayBack.newBuilder();

        builder.setBattletype(BattleMessage.BattleType.forNumber(module.getType().getNumber()));
        builder.setBattlecode(module.getCode());
        // 封装阵容
        for (Entry<Position, FighterModule> entry : module.getTeamA().fighters().entrySet()) {
            builder.addFormat(fighterInfo(entry.getValue(), entry.getKey(), true));
        }
        for (Entry<Position, FighterModule> entry : module.getTeamB().fighters().entrySet()) {
            builder.addFormat(fighterInfo(entry.getValue(), entry.getKey(), false));
        }
        if (module.getTeamA().getWeapon() != null) {
            builder.addFormat(niubeeInfo(module.getTeamA().getWeapon(), true));
        }
        if (module.getTeamB().getWeapon() != null) {
            builder.addFormat(niubeeInfo(module.getTeamB().getWeapon(), false));
        }
        if (module.getTeamA().getPokemonMoudle() != null) {
            builder.addFormat(therionInfo(module.getTeamA().getPokemonMoudle(), true));
        }
        if (module.getTeamB().getPokemonMoudle() != null) {
            builder.addFormat(therionInfo(module.getTeamB().getPokemonMoudle(), false));
        }
        // 封装战斗记录
        builder.setBattle(module.getRecord());
        // 封装统计数据
        for (StatisticFighter fighter : module.getStatistics()) {
            BattleMessage.FighterResult.Builder result = BattleMessage.FighterResult.newBuilder();
            result.setHpc(fighter.getHpc());
            result.setCur(fighter.getCur());
            result.setDmg(fighter.getDmg());
            result.setHut(fighter.getHut());
            result.setPosition(BattleMessage.Position.forNumber(fighter.getPos().getNumber()));
            builder.addStatistic(result);
        }
        // 封装战斗结果
        builder.setResult(module.getBattleResult().getNumber());
        // 战斗更详细的结果
        if (module.getBattleDetailResult() != null) builder.setDetailResult(module.getBattleDetailResult().getNumber());
        // 玩家信息 左
        builder.addPlayerInfo(playerBattleInfo(module.getTeamA(), true));
        // 玩家信息 右
        builder.addPlayerInfo(playerBattleInfo(module.getTeamB(), false));

        builder.setStarttime(module.timeline().getStartTime().getMillis());
        builder.setEndtime(module.timeline().getEndTime().getMillis());
        builder.setSkip(module.isSkip());

        return builder.build();
    }

    public BattleMessage.BattleClear battleClear(BattleRecord module) {
        BattleMessage.BattleClear.Builder builder = BattleMessage.BattleClear.newBuilder();

        builder.setBattletype(BattleMessage.BattleType.valueOf(module.getType().name()));
        builder.setBattlecode(module.getCode());
        // 封装阵容
        for (Entry<Position, FighterModule> entry : module.getTeamA().fighters().entrySet()) {
            builder.addFormat(fighterInfo(entry.getValue(), entry.getKey(), true));
        }
        for (Entry<Position, FighterModule> entry : module.getTeamB().fighters().entrySet()) {
            builder.addFormat(fighterInfo(entry.getValue(), entry.getKey(), false));
        }
        if (module.getTeamA().getWeapon() != null) {
            builder.addFormat(niubeeInfo(module.getTeamA().getWeapon(), true));
        }
        if (module.getTeamB().getWeapon() != null) {
            builder.addFormat(niubeeInfo(module.getTeamB().getWeapon(), false));
        }
        if (module.getTeamA().getPokemonMoudle() != null) {
            builder.addFormat(therionInfo(module.getTeamA().getPokemonMoudle(), true));
        }
        if (module.getTeamB().getPokemonMoudle() != null) {
            builder.addFormat(therionInfo(module.getTeamB().getPokemonMoudle(), false));
        }

        // 封装统计数据
        for (StatisticFighter fighter : module.getStatistics()) {
            BattleMessage.FighterResult.Builder result = BattleMessage.FighterResult.newBuilder();
            result.setHpc(fighter.getHpc());
            result.setCur(fighter.getCur());
            result.setDmg(fighter.getDmg());
            result.setHut(fighter.getHut());
            result.setPosition(BattleMessage.Position.forNumber(fighter.getPos().getNumber()));
            builder.addStatistic(result);
        }
        // 封装战斗结果
        builder.setResult(module.getBattleResult().getNumber());
        // 战斗更详细结果
        if (module.getBattleDetailResult() != null) builder.setDetailResult(module.getBattleDetailResult().getNumber());
        // 玩家信息 左
        builder.addPlayerInfo(playerBattleInfo(module.getTeamA(), true));
        // 玩家信息 右
        builder.addPlayerInfo(playerBattleInfo(module.getTeamB(), false));

        builder.setEndtime(module.timeline().getEndTime().getMillis());

        return builder.build();
    }

    public Fighter transformPosition(BattleMessage.Position position, Team team_a, Team team_b) {
        switch (position) {
            case BDL:
                return team_a.getFighterByPosition(Position.BD);
            case BDR:
                return team_b.getFighterByPosition(Position.BD);
            case BML:
                return team_a.getFighterByPosition(Position.BM);
            case BMR:
                return team_b.getFighterByPosition(Position.BM);
            case BUL:
                return team_a.getFighterByPosition(Position.BU);
            case BUR:
                return team_b.getFighterByPosition(Position.BU);
            case FDL:
                return team_a.getFighterByPosition(Position.FD);
            case FDR:
                return team_b.getFighterByPosition(Position.FD);
            case FML:
                return team_a.getFighterByPosition(Position.FM);
            case FMR:
                return team_b.getFighterByPosition(Position.FM);
            case FUL:
                return team_a.getFighterByPosition(Position.FU);
            case FUR:
                return team_b.getFighterByPosition(Position.FU);
            default:
                return null;
        }
    }

    // 战力================================================================================

    /**
     * 更新英雄 看看是否影响战力
     */
    public void heroUpdate(String playerCode, Hero hero) {
        Format format = new FormatHandle().get(playerCode, FormatType.普通);
        Collection<Hero> formatHeros = new FormatHandle().formatHeros(playerCode, format).values();
        for (Hero formatHero : formatHeros) {
            if (formatHero.getCode().equals(hero.getCode())) {
                // 推送战力 依据武将的变化 如果是上阵武将的话 则推送战力变化  并且只需重新计算自己的战力，其他上阵武将战力从缓存获取
                new NotificationHandle().notifyBattlePower(playerCode, power(playerCode, formatHeros, format, hero));
                return;
            }
        }
    }

    public void powerUpdate(String playerCode) {
        Runnable runnable = () -> {
            new NotificationHandle().notifyBattlePower(playerCode, power(playerCode, FormatType.普通));
        };
        ThreadPoolManager.getInstance().execute(runnable);
    }

    public long power(String playerCode, FormatType formatType) {
        Format format = new FormatHandle().get(playerCode, formatType);
        return power(playerCode, new FormatHandle().formatHeros(playerCode, format).values(), format);
    }

    public long power(String playerCode, Collection<Hero> heros, Format format) {
        long power = 0;
        for (Hero hero : heros) {
            try {
                power += power(playerCode, hero, format);
            } catch (Exception e) {
            }
        }
        return power;
    }

    public long power(String playerCode, Collection<Hero> heros, Format format, Hero needCalculateHero) {
        long power = 0;
        try {
            for (Hero hero : heros) {
                if (hero.getCode().equals(needCalculateHero.getCode())) {
                    power += power(playerCode, hero, format);
                } else {
                    power += hero.getPower();
                }
            }
        } catch (Exception e) {
        }
        return power;
    }

    public long power(String playerCode, Hero hero) {
        Format format = new FormatHandle().get(playerCode, FormatType.普通);
        return power(playerCode, hero, format);
    }

    public long power(String playerCode, Hero hero, Format format) {
        Long power = calculatePower(playerCode, hero, format);
        return power;
    }

    // 战斗属性封装================================================================================

    static public PropertyData packProperty(String playerCode, Hero hero) {
        Format format = new FormatHandle().get(playerCode, FormatType.普通);
        PropertyData propertyData = packProperty(playerCode, hero, format);
        return propertyData;
    }

    static public PropertyData packProperty(String playerCode, Hero hero, Format format) {
        PlayTypeModule playTypeModule = PlayTypeModule.get(playerCode);

        //!!!第一步：武将基础属性 herodata herograde herostagecost
        herodata _herodata = DataCenter.getData(hero.getDataId(), herodata.class);

        PropertyData propertyData = packProperty武将基础属性(_herodata, hero.getLevel(), hero.getStage());
        long value1 = propertyData.getValue(PropertyType.P_速度);//成长的速度加成  不计入战力公式

        //!!!第二步：以下先进行额外计算
        PropertyData propertyDataAdd = new PropertyData();
        propertyDataAdd.addAllValue(packProperty升星属性(_herodata, hero.getStar()));
        battleLogger(1, "升星-攻击：" + propertyDataAdd.getValue(PropertyType.P_攻击) + "物防：" + propertyDataAdd.getValue(PropertyType.P_防御) + "法防：" + propertyDataAdd.getValue(PropertyType.P_法防) + "生命:" + propertyDataAdd.getValue(PropertyType.P_生命) + "攻击增幅：" + propertyDataAdd.getValue(PropertyType.P_攻击增幅) + "防御增幅：" + propertyDataAdd.getValue(PropertyType.P_防御增幅) + "法防增幅：" + propertyDataAdd.getValue(PropertyType.P_法防增幅) + "生命增幅：" + propertyDataAdd.getValue(PropertyType.P_生命增幅));
        // 装备套装 equipdata equipfetterdata
        propertyDataAdd.addAllValue(packProperty装备属性(hero.getEquips()));
        battleLogger(1, "装备-攻击：" + propertyDataAdd.getValue(PropertyType.P_攻击) + "物防：" + propertyDataAdd.getValue(PropertyType.P_防御) + "法防：" + propertyDataAdd.getValue(PropertyType.P_法防) + "生命:" + propertyDataAdd.getValue(PropertyType.P_生命) + "攻击增幅：" + propertyDataAdd.getValue(PropertyType.P_攻击增幅) + "防御增幅：" + propertyDataAdd.getValue(PropertyType.P_防御增幅) + "法防增幅：" + propertyDataAdd.getValue(PropertyType.P_法防增幅) + "生命增幅：" + propertyDataAdd.getValue(PropertyType.P_生命增幅));
        // 魂玉 souldata soulatt soulrefine
        propertyDataAdd.addAllValue(packProperty魂玉(playerCode, hero));
        battleLogger(1, "魂玉-攻击：" + propertyDataAdd.getValue(PropertyType.P_攻击) + "物防：" + propertyDataAdd.getValue(PropertyType.P_防御) + "法防：" + propertyDataAdd.getValue(PropertyType.P_法防) + "生命:" + propertyDataAdd.getValue(PropertyType.P_生命) + "攻击增幅：" + propertyDataAdd.getValue(PropertyType.P_攻击增幅) + "防御增幅：" + propertyDataAdd.getValue(PropertyType.P_防御增幅) + "法防增幅：" + propertyDataAdd.getValue(PropertyType.P_法防增幅) + "生命增幅：" + propertyDataAdd.getValue(PropertyType.P_生命增幅));
        // 羁绊 fetterdata 乌巢format是null
        if (format != null) {
            propertyDataAdd.addAllValue(packProperty羁绊(playerCode, hero, format));
        }
        battleLogger(1, "羁绊-攻击：" + propertyDataAdd.getValue(PropertyType.P_攻击) + "增伤：" + propertyDataAdd.getValue(PropertyType.P_增伤) + "减伤：" + propertyDataAdd.getValue(PropertyType.P_减伤) + "物防：" + propertyDataAdd.getValue(PropertyType.P_防御) + "法防：" + propertyDataAdd.getValue(PropertyType.P_法防) + "生命:" + propertyDataAdd.getValue(PropertyType.P_生命) + "攻击增幅：" + propertyDataAdd.getValue(PropertyType.P_攻击增幅) + "防御增幅：" + propertyDataAdd.getValue(PropertyType.P_防御增幅) + "法防增幅：" + propertyDataAdd.getValue(PropertyType.P_法防增幅) + "生命增幅：" + propertyDataAdd.getValue(PropertyType.P_生命增幅));


        //todo 兵符槽PickedTroop(已放缓存)
        propertyDataAdd.addAllValue(packProperty兵符和兵符槽(playerCode, _herodata, hero, format, playTypeModule));
        battleLogger(1, "兵符和兵符槽-攻击：" + propertyDataAdd.getValue(PropertyType.P_攻击) + "物防：" + propertyDataAdd.getValue(PropertyType.P_防御) + "法防：" + propertyDataAdd.getValue(PropertyType.P_法防) + "生命:" + propertyDataAdd.getValue(PropertyType.P_生命) + "攻击增幅：" + propertyDataAdd.getValue(PropertyType.P_攻击增幅) + "防御增幅：" + propertyDataAdd.getValue(PropertyType.P_防御增幅) + "法防增幅：" + propertyDataAdd.getValue(PropertyType.P_法防增幅) + "生命增幅：" + propertyDataAdd.getValue(PropertyType.P_生命增幅));

        //todo 神器 weapon(已放缓存)
        if (format != null && format.ismember(hero.getCode()) && format.getNb() > 0) {
            propertyDataAdd.addAllValue(packProperty神器(playTypeModule));
            battleLogger(1, "神器-攻击：" + propertyDataAdd.getValue(PropertyType.P_攻击) + "物防：" + propertyDataAdd.getValue(PropertyType.P_防御) + "法防：" + propertyDataAdd.getValue(PropertyType.P_法防) + "生命:" + propertyDataAdd.getValue(PropertyType.P_生命) + "攻击增幅：" + propertyDataAdd.getValue(PropertyType.P_攻击增幅) + "防御增幅：" + propertyDataAdd.getValue(PropertyType.P_防御增幅) + "法防增幅：" + propertyDataAdd.getValue(PropertyType.P_法防增幅) + "生命增幅：" + propertyDataAdd.getValue(PropertyType.P_生命增幅));
        }

        //todo 形象 avatar，avatar形象暂时不增加属性(已放缓存)
        propertyDataAdd.addAllValue(packProperty形象(playTypeModule));
        battleLogger(1, "形象-攻击：" + propertyDataAdd.getValue(PropertyType.P_攻击) + "物防：" + propertyDataAdd.getValue(PropertyType.P_防御) + "法防：" + propertyDataAdd.getValue(PropertyType.P_法防) + "生命:" + propertyDataAdd.getValue(PropertyType.P_生命) + "攻击增幅：" + propertyDataAdd.getValue(PropertyType.P_攻击增幅) + "防御增幅：" + propertyDataAdd.getValue(PropertyType.P_防御增幅) + "法防增幅：" + propertyDataAdd.getValue(PropertyType.P_法防增幅) + "生命增幅：" + propertyDataAdd.getValue(PropertyType.P_生命增幅));

        //todo 称号 title(已放缓存)
        propertyDataAdd.addAllValue(packProperty称号(playTypeModule));
        battleLogger(1, "称号-攻击：" + propertyDataAdd.getValue(PropertyType.P_攻击) + "物防：" + propertyDataAdd.getValue(PropertyType.P_防御) + "法防：" + propertyDataAdd.getValue(PropertyType.P_法防) + "生命:" + propertyDataAdd.getValue(PropertyType.P_生命) + "攻击增幅：" + propertyDataAdd.getValue(PropertyType.P_攻击增幅) + "防御增幅：" + propertyDataAdd.getValue(PropertyType.P_防御增幅) + "法防增幅：" + propertyDataAdd.getValue(PropertyType.P_法防增幅) + "生命增幅：" + propertyDataAdd.getValue(PropertyType.P_生命增幅));

        //todo 联盟科技 unionskill(已放缓存)
        propertyDataAdd.addAllValue(packProperty联盟(playTypeModule, hero));
        battleLogger(1, "联盟-攻击：" + propertyDataAdd.getValue(PropertyType.P_攻击) + "物防：" + propertyDataAdd.getValue(PropertyType.P_防御) + "法防：" + propertyDataAdd.getValue(PropertyType.P_法防) + "生命:" + propertyDataAdd.getValue(PropertyType.P_生命) + "攻击增幅：" + propertyDataAdd.getValue(PropertyType.P_攻击增幅) + "防御增幅：" + propertyDataAdd.getValue(PropertyType.P_防御增幅) + "法防增幅：" + propertyDataAdd.getValue(PropertyType.P_法防增幅) + "生命增幅：" + propertyDataAdd.getValue(PropertyType.P_生命增幅));

        //todo 玉玺(已放缓存)
        propertyDataAdd.addAllValue(packProperty玉玺(playTypeModule, _herodata));
        battleLogger(1, "玉玺-攻击：" + propertyDataAdd.getValue(PropertyType.P_攻击) + "物防：" + propertyDataAdd.getValue(PropertyType.P_防御) + "法防：" + propertyDataAdd.getValue(PropertyType.P_法防) + "生命:" + propertyDataAdd.getValue(PropertyType.P_生命) + "攻击增幅：" + propertyDataAdd.getValue(PropertyType.P_攻击增幅) + "防御增幅：" + propertyDataAdd.getValue(PropertyType.P_防御增幅) + "法防增幅：" + propertyDataAdd.getValue(PropertyType.P_法防增幅) + "生命增幅：" + propertyDataAdd.getValue(PropertyType.P_生命增幅));

        //todo 神兽(已放缓存)
        propertyDataAdd.addAllValue(packProperty神兽(playerCode, playTypeModule));
        battleLogger(1, "神兽-攻击：" + propertyDataAdd.getValue(PropertyType.P_攻击) + "物防：" + propertyDataAdd.getValue(PropertyType.P_防御) + "法防：" + propertyDataAdd.getValue(PropertyType.P_法防) + "生命:" + propertyDataAdd.getValue(PropertyType.P_生命) + "攻击增幅：" + propertyDataAdd.getValue(PropertyType.P_攻击增幅) + "防御增幅：" + propertyDataAdd.getValue(PropertyType.P_防御增幅) + "法防增幅：" + propertyDataAdd.getValue(PropertyType.P_法防增幅) + "生命增幅：" + propertyDataAdd.getValue(PropertyType.P_生命增幅));

        //todo 主公统御加点
        propertyDataAdd.addAllValue(packProperty主公统御(playerCode,playTypeModule));
        battleLogger(1, "主公统御-攻击：" + propertyDataAdd.getValue(PropertyType.P_攻击) + "物防：" + propertyDataAdd.getValue(PropertyType.P_防御) + "法防：" + propertyDataAdd.getValue(PropertyType.P_法防) + "生命:" + propertyDataAdd.getValue(PropertyType.P_生命) + "攻击增幅：" + propertyDataAdd.getValue(PropertyType.P_攻击增幅) + "防御增幅：" + propertyDataAdd.getValue(PropertyType.P_防御增幅) + "法防增幅：" + propertyDataAdd.getValue(PropertyType.P_法防增幅) + "生命增幅：" + propertyDataAdd.getValue(PropertyType.P_生命增幅));

        //todo 阵营塔-四象归一(已放缓存)
        propertyDataAdd.addAllValue(packProperty阵营塔(playTypeModule));
        battleLogger(1, "阵营塔-四象归一-攻击：" + propertyDataAdd.getValue(PropertyType.P_攻击) + "物防：" + propertyDataAdd.getValue(PropertyType.P_防御) + "法防：" + propertyDataAdd.getValue(PropertyType.P_法防) + "生命:" + propertyDataAdd.getValue(PropertyType.P_生命) + "攻击增幅：" + propertyDataAdd.getValue(PropertyType.P_攻击增幅) + "防御增幅：" + propertyDataAdd.getValue(PropertyType.P_防御增幅) + "法防增幅：" + propertyDataAdd.getValue(PropertyType.P_法防增幅) + "生命增幅：" + propertyDataAdd.getValue(PropertyType.P_生命增幅));

//        //todo 斩关夺隘观星(已放缓存,旧版本 暂时弃用)
//        propertyDataAdd.addAllValue(packProperty斩关夺隘old(playTypeModule));

        //todo 斩关夺隘观星(已放缓存)
        propertyDataAdd.addAllValue(packProperty斩关夺隘(playTypeModule));



        //!!!第三步 计算基于基础属性的增幅
        propertyData.addAllValue(packProperty属性增幅(propertyData, propertyDataAdd));
        battleLogger(1, "加各种增幅后-攻击：" + propertyData.getValue(PropertyType.P_攻击) + "物防：" + propertyData.getValue(PropertyType.P_防御) + "法防：" + propertyData.getValue(PropertyType.P_法防) + "生命:" + propertyData.getValue(PropertyType.P_生命));

        //!!!第四步 把额外增加的非百分比属性加进来
        propertyData.addAllValue(propertyDataAdd);
        battleLogger(1, "加各种固定值-攻击：" + propertyData.getValue(PropertyType.P_攻击) + "物防：" + propertyData.getValue(PropertyType.P_防御) + "法防：" + propertyData.getValue(PropertyType.P_法防) + "生命:" + propertyData.getValue(PropertyType.P_生命));

        long value2 = propertyData.getValue(PropertyType.P_速度);//总的速度

        propertyData.setValue(PropertyType.P_速度增幅, value2 - value1);

        //清理增幅比例
        clearRate(propertyData);
        return propertyData;
    }

    /**
     * 斩关夺隘星星养成
     * @param playTypeModule
     * @return
     */
    private static PropertyData packProperty斩关夺隘(PlayTypeModule playTypeModule) {
        return playTypeModule.getPassBarrierStars();
    }




//    /**
//     * 斩关夺隘星星养成
//     * @param playTypeModule
//     * @return
//     */
//    private static PropertyData packProperty斩关夺隘old(PlayTypeModule playTypeModule) {
//        return playTypeModule.getCaptureStrategic();
//    }

    /**
     * 神兽和神兽装备属性加成
     *
     * @param playerCode
     * @param playTypeModule
     * @return
     */
    private static PropertyData packProperty神兽(String playerCode, PlayTypeModule playTypeModule) {
        return playTypeModule.getTherion();
    }

    private static PropertyData packProperty阵营塔(PlayTypeModule playTypeModule) {
        return playTypeModule.getFourSeal();
    }


    /**
     * 主公统御属性加成
     *
     * @param playerCode
     * @param playTypeModule
     * @return
     */
    private static PropertyData packProperty主公统御(String playerCode, PlayTypeModule playTypeModule) {
        return playTypeModule.getPlayerCommand();
    }


    /**
     * 计算兵符和兵符槽的属性
     *
     * @param playerCode
     * @param herodata
     * @param hero
     * @param format
     * @return
     */
    private static PropertyData packProperty兵符和兵符槽(String playerCode, herodata herodata, Hero hero, Format format, PlayTypeModule playTypeModule) {

        int type = herodata.getPower(); // 所属阵营
        PropertyData propertyData = playTypeModule.getPickedTroop().get(type) == null ? new PropertyData() : playTypeModule.getPickedTroop().get(type);

        //该英雄属于前排则加属性
        if (hero.getCode().equals(format.getFu()) || hero.getCode().equals(format.getFm()) || hero.getCode().equals(format.getFd())) {
            //添加属性
            PropertyData slotPropertyData = playTypeModule.getPickedTroopSlot().get(1);
            propertyData.addAllValue(slotPropertyData);
        }

        //该英雄属于后排则加属性
        if (hero.getCode().equals(format.getBd()) || hero.getCode().equals(format.getBm()) || hero.getCode().equals(format.getBu())) {
            //添加属性
            PropertyData slotPropertyData = playTypeModule.getPickedTroopSlot().get(2);
            propertyData.addAllValue(slotPropertyData);
        }

        //全体加
        PropertyData slotPropertyData = playTypeModule.getPickedTroopSlot().get(3);
        propertyData.addAllValue(slotPropertyData);

        return propertyData;
    }


    /**
     * 计算词条的加成
     *
     * @param entryId
     * @param value
     * @param propertyData
     * @param hero
     * @param format
     */
    private static void computePropertryForEntry(ArrayList<Integer> entryId, ArrayList<Integer> value, PropertyData propertyData, Hero hero, Format format) {
        for (int i = 0; i < entryId.size(); i++) {
            commandertallyrandom data = DataCenter.getData(entryId.get(i), commandertallyrandom.class);
            int attributetype = data.getAttributetype();//属性类型
            int target = data.getTarget();//目标   1.前排   2.后排  3.全体
            switch (target) {
                case 1:
                    //该英雄属于前排则加属性
                    if (hero.getCode().equals(format.getFu()) || hero.getCode().equals(format.getFm()) || hero.getCode().equals(format.getFd())) {
                        //添加属性
                        propertyData.addValue(PropertyType.forNumber(attributetype), value.get(i));
                    }
                    break;
                case 2:
                    //该英雄属于后排则加属性
                    if (hero.getCode().equals(format.getBd()) || hero.getCode().equals(format.getBm()) || hero.getCode().equals(format.getBu())) {
                        //添加属性
                        propertyData.addValue(PropertyType.forNumber(attributetype), value.get(i));
                    }
                    break;
                case 3:
                    //全体加
                    propertyData.addValue(PropertyType.forNumber(attributetype), value.get(i));
                    break;
            }
        }
    }


    /**
     * 计算武将的基础属性
     *
     * @param _herodata
     * @param level
     * @param stage
     * @return
     */
    static public PropertyData packProperty武将基础属性(herodata _herodata, int level, int stage) {
        int heroId = _herodata.getId();
        herograde _herograde = DataCenter.getData(heroId, herograde.class);
        battleLogger(1, "-------------------packProperty武将基础属性-------------------" + heroId + "-------------------");
        herostagecost _herostagecost = DataCenter.getData(stage, herostagecost.class);
        PropertyData propertyData = new PropertyData();
        propertyData.addAllValue(getHeroPropertyData(_herodata));
        battleLogger(1, "基础-攻击：" + propertyData.getValue(PropertyType.P_攻击) + "物防：" + propertyData.getValue(PropertyType.P_防御) + "法防：" + propertyData.getValue(PropertyType.P_法防) + "生命:" + propertyData.getValue(PropertyType.P_生命));
        propertyData.addAllValue(getHerogradePropertyData(_herograde, level));
        battleLogger(1, "升级-攻击：" + propertyData.getValue(PropertyType.P_攻击) + "物防：" + propertyData.getValue(PropertyType.P_防御) + "法防：" + propertyData.getValue(PropertyType.P_法防) + "生命:" + propertyData.getValue(PropertyType.P_生命));
        propertyData.setValue(PropertyType.P_速度, propertyData.getValue(PropertyType.P_速度) / 10000);
        propertyData.addAllValue(getHeroStagePropertyRateData(_herostagecost));
        propertyData.addAllValue(packProperty属性增幅(propertyData, propertyData));
        battleLogger(1, "升阶-阶" + stage + "攻击：" + propertyData.getValue(PropertyType.P_攻击) + "物防：" + propertyData.getValue(PropertyType.P_防御) + "法防：" + propertyData.getValue(PropertyType.P_法防) + "生命:" + propertyData.getValue(PropertyType.P_生命) + "攻击增幅：" + propertyData.getValue(PropertyType.P_攻击增幅) + "物防增幅：" + propertyData.getValue(PropertyType.P_防御增幅) + "法防增幅：" + propertyData.getValue(PropertyType.P_法防增幅) + "生命增幅：" + propertyData.getValue(PropertyType.P_生命增幅));
        propertyData.addAllValue(getHeroStagePropertyData(_herostagecost));
        clearRate(propertyData);
        return propertyData;
    }

    /**
     * 清理增幅数据
     *
     * @param propertyData
     */
    public static void clearRate(PropertyData propertyData) {
        propertyData.setValue(PropertyType.P_攻击增幅, 0);
        propertyData.setValue(PropertyType.P_防御增幅, 0);
        propertyData.setValue(PropertyType.P_法防增幅, 0);
        propertyData.setValue(PropertyType.P_生命增幅, 0);
    }

    public static PropertyData packProperty升星属性(herodata _herodata, int star) {
        int heroId = _herodata.getId();
        if (star <= _herodata.getStartcs()) {
            star = _herodata.getStartcs();
        }
        heroadvanced _heroadvanced = DataCenter.getData(String.format("%d_%d", heroId, star), heroadvanced.class);
        PropertyData propertyData = new PropertyData();
        propertyData.addAllValue(getHeroStarPropertyData(_heroadvanced));
        return propertyData;
    }

    private static PropertyData getHeroPropertyData(herodata data) {
        PropertyData propertyData = new PropertyData();
        propertyData.setValue(PropertyType.P_速度, data.getSpeed());
        propertyData.setValue(PropertyType.P_攻击, data.getAttack());
        propertyData.setValue(PropertyType.P_防御, data.getPdefense());
        propertyData.setValue(PropertyType.P_法防, data.getSefense());
        propertyData.setValue(PropertyType.P_生命, data.getLife());
        propertyData.setValue(PropertyType.P_暴击, data.getStrike());
        propertyData.setValue(PropertyType.P_抗暴, data.getAntiriot());
        propertyData.setValue(PropertyType.P_暴伤, data.getBurstdps());
        propertyData.setValue(PropertyType.P_韧性, data.getBurstdrop());
        propertyData.setValue(PropertyType.P_命中, data.getFit());
        propertyData.setValue(PropertyType.P_闪避, data.getDodge());
        propertyData.setValue(PropertyType.P_控制, data.getControl());
        propertyData.setValue(PropertyType.P_抗控, data.getResist());
        propertyData.setValue(PropertyType.P_治疗, data.getTreatment());
        propertyData.setValue(PropertyType.P_受疗, data.getTherapy());
        propertyData.setValue(PropertyType.P_增伤, data.getPdefenseup());
        propertyData.setValue(PropertyType.P_减伤, data.getPdefenseguard());
        propertyData.setValue(PropertyType.P_法增, data.getSefenseup());
        propertyData.setValue(PropertyType.P_法减, data.getEfenseguard());
        return propertyData;
    }

    private static PropertyData getHerogradePropertyData(herograde data, int level) {
        PropertyData propertyData = new PropertyData();
        propertyData.setValue(PropertyType.P_攻击, BattleFomula.武将升级攻击属性提升(level, data.getAttack()));
        propertyData.setValue(PropertyType.P_防御, BattleFomula.武将升级物防属性提升(level, data.getPdefense()));
        propertyData.setValue(PropertyType.P_法防, BattleFomula.武将升级法防属性提升(level, data.getSefense()));
        propertyData.setValue(PropertyType.P_生命, BattleFomula.武将升级生命属性提升(level, data.getLife()));
        //大于350级不再进行速度提升
        long 武将升级速度属性提升 = level >= 350 ? BattleFomula.武将升级速度属性提升(350, data.getSpeed()) : BattleFomula.武将升级速度属性提升(level, data.getSpeed());
        propertyData.setValue(PropertyType.P_速度, 武将升级速度属性提升);
        return propertyData;
    }

    /**
     * 得到升阶得到的百分比属性增幅
     *
     * @param data
     * @return
     */
    private static PropertyData getHeroStagePropertyRateData(herostagecost data) {
        PropertyData propertyData = new PropertyData();
        propertyData.setValue(PropertyType.P_攻击增幅, data.getAttackscale());
        propertyData.setValue(PropertyType.P_防御增幅, data.getPdefensescale());
        propertyData.setValue(PropertyType.P_法防增幅, data.getSefensescale());
        propertyData.setValue(PropertyType.P_生命增幅, data.getLifescale());
        return propertyData;
    }

    /**
     * 得到升阶得到的固定增长值
     *
     * @param data
     * @return
     */
    private static PropertyData getHeroStagePropertyData(herostagecost data) {
        PropertyData propertyData = new PropertyData();
        propertyData.setValue(PropertyType.P_攻击, data.getAttack());
        propertyData.setValue(PropertyType.P_防御, data.getPdefense());
        propertyData.setValue(PropertyType.P_法防, data.getSefense());
        propertyData.setValue(PropertyType.P_生命, data.getLife());
        return propertyData;
    }

    private static PropertyData getHeroStarPropertyData(heroadvanced data) {
        PropertyData propertyData = new PropertyData();
        propertyData.setValue(PropertyType.P_攻击增幅, data.getAttackscale());
        propertyData.setValue(PropertyType.P_生命增幅, data.getLifescale());
        propertyData.setValue(PropertyType.P_防御增幅, data.getPdefensescale());
        propertyData.setValue(PropertyType.P_法防增幅, data.getSefensescale());
        return propertyData;
    }

    // 装备属性封装================================================================================
    static public PropertyData packProperty装备属性(int[] equips) {
        PropertyData propertyData = new PropertyData();
        for (int i = 0; i < equips.length; i++) {
            int equip = equips[i];
            equipdata _equipdata = DataCenter.getData(equip, equipdata.class);
            if (_equipdata == null) {
                continue;
            }
            propertyData.addAllValue(getEquipPropertyData(_equipdata));
        }
        // 套装
        Map<String, equipfetterdata> fetterdatas = DataCenter.getAllData(equipfetterdata.class);
        for (equipfetterdata fetterdata : fetterdatas.values()) {
            int count = -2;
            for (int i = 0; i < equips.length; i++) {
                for (int j = 0; j < fetterdata.getEquipid().length; j++) {
                    if (equips[i] == fetterdata.getEquipid()[j]) {
                        count++;
                    }
                }
            }
            if (count < 0 || count > 2) {
                continue;
            }
            for (int i = 0; i <= count; i++) {
                propertyData.addValue(PropertyType.forNumber(fetterdata.getType()[i]), fetterdata.getPercentage()[i]);
            }
        }
        return propertyData;
    }

    private static PropertyData getEquipPropertyData(equipdata data) {
        PropertyData propertyData = new PropertyData();
        propertyData.setValue(PropertyType.forNumber(data.getAttributetype()), data.getAttributenum());
        propertyData.setValue(PropertyType.forNumber(data.getPercentagetype()), data.getPercentagenum());
        return propertyData;
    }

    // 魂玉属性封装================================================================================
    private static PropertyData packProperty魂玉(String playerCode, Hero hero) {
        PropertyData propertyData = new PropertyData();
        Soul soulA = Soul.get(playerCode, hero.getSoulA());
        Soul soulB = Soul.get(playerCode, hero.getSoulB());
        getSoulPropertyData(soulA, propertyData);
        getSoulPropertyData(soulB, propertyData);
        return propertyData;
    }

    private static void getSoulPropertyData(Soul soul, PropertyData propertyData) {
        if (soul == null) {
            return;
        }
        for (Integer id : soul.getPropertyIds()) {
            soulatt _soulatt = DataCenter.getData(id, soulatt.class);
            if (_soulatt == null) {
                continue;
            }
            long attributenum = _soulatt.getAttributenum();
            soulrefine _soulrefine = DataCenter.getData(soul.getRefine(), soulrefine.class);

            if (_soulrefine != null) {
                attributenum += attributenum * _soulrefine.getAttributeratio() / 10000;
            }
            propertyData.addValue(PropertyType.forNumber(_soulatt.getAttributetype()), attributenum);
        }
    }

    // 羁绊属性封装================================================================================

    public static PropertyData packProperty羁绊(String playerCode, Hero hero, Format format) {
        Collection<Hero> heros = new FormatHandle().formatHeros(playerCode, format).values();
        return packProperty羁绊(heros);
    }

    public static PropertyData packProperty羁绊(Collection<Hero> heros) {
        Map<Camp, Integer> 计数 = new HashMap<>();
        for (Hero heroo : heros) {
            int dataId = heroo.getDataId();
            herodata data = DataCenter.getData(dataId, herodata.class);
            Camp camp = Camp.forNumber(data.getPower());
            int number = 0;
            if (计数.containsKey(camp)) {
                number = 计数.get(camp);
            }
            计数.put(camp, number + 1);
        }
        Set<fetterdata> fetterList = new HashSet<>();
        boolean allhaveone = true;
        for (Camp camp : Camp.values()) {
            if (!计数.containsKey(camp)) {
                allhaveone = false;
                continue;
            }
            int number = 计数.get(camp);
            if (number > 1) {
                allhaveone = false;
            }
            fetterdata data = findfetter(camp.getNumber(), number);
            if (data != null) {
                fetterList.add(data);
            }
        }
        if (allhaveone) {
            fetterdata data = findfetter(7, 6);// 各阵营都有一个
            fetterList.add(data);
        }
        PropertyData propertyData = new PropertyData();
        for (fetterdata data : fetterList) {
            for (int i = 0; i < data.getType().length; i++) {
                int type = data.getType()[i];
                int value = data.getPercentage()[i];
                PropertyType propertyType = PropertyType.forNumber(type);
                if (propertyType == null || value == 0) {
                    continue;
                }
                propertyData.addValue(propertyType, value);
            }
        }
        return propertyData;
    }

    private static fetterdata findfetter(int camp, int number) {
        Collection<fetterdata> datas = DataCenter.getAllData(fetterdata.class).values();
        for (fetterdata data : datas) {
            if (data.getFettertype() == camp && data.getFetternum() == number) {
                return data;
            }
        }
        return null;
    }


    // 神兵属性封装================================================================================
    static public PropertyData packProperty神器(PlayTypeModule playTypeModule) {
        PropertyData propertyData = playTypeModule.getWeapon();
        return propertyData;
    }

    // 玉玺属性封装================================================================================
    static public PropertyData packProperty玉玺(PlayTypeModule playTypeModule, herodata _herodata) {
        int type = _herodata.getPower(); // 所属阵营

        PropertyData propertyData = playTypeModule.getJadeSeal().get(type) == null ? new PropertyData() : playTypeModule.getJadeSeal().get(type);
        return propertyData;
    }

    // 形象称号================================================================================

    private static PropertyData packProperty形象(PlayTypeModule playTypeModule) {
        PropertyData propertyData = playTypeModule.getAvatar();
        return propertyData;
    }

    private static PropertyData packProperty称号(PlayTypeModule playTypeModule) {
        PropertyData propertyData = playTypeModule.getTitle();
        return propertyData;
    }

    // 联盟科技属性封装================================================================================
    private static PropertyData packProperty联盟(PlayTypeModule playTypeModule, Hero hero) {
        herodata _herodata = DataCenter.getData(hero.getDataId(), herodata.class);
        int herotype = _herodata.getHerotype();
        return playTypeModule.getUnion().get(herotype);
    }

    // 属性增幅================================================================================
    public static PropertyData packProperty属性增幅(PropertyData propertyData, PropertyData propertyDataAdd) {
        PropertyData propertyData1 = new PropertyData();
        propertyData1.setValue(PropertyType.P_攻击, PropertyData.valueAdd(propertyData.getValue(PropertyType.P_攻击), propertyDataAdd.getValue(PropertyType.P_攻击增幅)));
        propertyData1.setValue(PropertyType.P_防御, PropertyData.valueAdd(propertyData.getValue(PropertyType.P_防御), propertyDataAdd.getValue(PropertyType.P_防御增幅)));
        propertyData1.setValue(PropertyType.P_法防, PropertyData.valueAdd(propertyData.getValue(PropertyType.P_法防), propertyDataAdd.getValue(PropertyType.P_法防增幅)));
        propertyData1.setValue(PropertyType.P_生命, PropertyData.valueAdd(propertyData.getValue(PropertyType.P_生命), propertyDataAdd.getValue(PropertyType.P_生命增幅)));
        return propertyData1;
    }


    //获取升阶的属性
    public PropertyData showPropertyDataToClassLevel(Hero hero) {
        herodata _herodata = DataCenter.getData(hero.getDataId(), herodata.class);
        int heroId = _herodata.getId();
        herograde _herograde = DataCenter.getData(heroId, herograde.class);
        herostagecost _herostagecostNext = DataCenter.getData(hero.getStage() + 1, herostagecost.class);
        herostagecost _herostagecostCurry = DataCenter.getData(hero.getStage(), herostagecost.class);

        if (_herostagecostNext == null) return new PropertyData();

        //下一阶增幅
        PropertyData propertyDataNext = new PropertyData();
        propertyDataNext.addAllValue(getHeroPropertyData(_herodata));
        propertyDataNext.addAllValue(getHerogradePropertyData(_herograde, hero.getLevel()));
        propertyDataNext.addAllValue(getHeroStagePropertyRateData(_herostagecostNext));
        PropertyData propertyData1 = packProperty属性增幅(propertyDataNext, propertyDataNext);
        //当前的增幅
        PropertyData propertyDataCurry = new PropertyData();
        propertyDataCurry.addAllValue(getHeroPropertyData(_herodata));
        propertyDataCurry.addAllValue(getHerogradePropertyData(_herograde, hero.getLevel()));
        propertyDataCurry.addAllValue(getHeroStagePropertyRateData(_herostagecostCurry));
        PropertyData propertyData2 = packProperty属性增幅(propertyDataCurry, propertyDataCurry);
        //两者相减获得最终的加成
        PropertyData returnPropertyData = subtractTwoPropertyData(propertyData1, propertyData2);
        return returnPropertyData;

    }

    //下一阶增长减去上一阶增长，获取真实增长值
    private PropertyData subtractTwoPropertyData(PropertyData propertyDataNext, PropertyData propertyDataCurry) {
        propertyDataNext.setValue(PropertyType.P_攻击, propertyDataNext.getValue(PropertyType.P_攻击) - propertyDataCurry.getValue(PropertyType.P_攻击));
        propertyDataNext.setValue(PropertyType.P_防御, propertyDataNext.getValue(PropertyType.P_防御) - propertyDataCurry.getValue(PropertyType.P_防御));
        propertyDataNext.setValue(PropertyType.P_法防, propertyDataNext.getValue(PropertyType.P_法防) - propertyDataCurry.getValue(PropertyType.P_法防));
        propertyDataNext.setValue(PropertyType.P_生命, propertyDataNext.getValue(PropertyType.P_生命) - propertyDataCurry.getValue(PropertyType.P_生命));
        return propertyDataNext;
    }


    //战斗，通过敌方等级计算敌方英雄星级和阶级
    public static HashMap<String, Integer> addStarAndStage(int heroid, int stage, int star, int level) {
        HashMap<String, Integer> returnMap = new HashMap<>();

        int finalStar = star;
        int finalStage = stage;
        try {
            //根据等级获取当前敌方的星级和阶级

            //升星表对应map  key:武将最高星级 value:武将id
            HashMap<Integer, Integer> map_heroadvanceddata = new HashMap<>();
            //计算能升的最大星级
            heroadvanceddata advanceddata = DataCenter.getData(heroid, heroadvanceddata.class);
            //当能转生（能升星）
            while (advanceddata != null) {
                map_heroadvanceddata.put(advanceddata.getStartop(), advanceddata.getId());
                advanceddata = DataCenter.getData(advanceddata.getEvolutionid(), heroadvanceddata.class);
            }

            //获取阶级  key 等级   value  阶级
            HashMap<Integer, Integer> mapForStage = new HashMap<>();
            ArrayList<Integer> arraryListForStage = new ArrayList<>();
            if (map_heroadvanceddata != null && map_heroadvanceddata.size() > 0) {
                Map<String, herostagecost> allData = DataCenter.getAllData(herostagecost.class);
                for (herostagecost herostagecost : allData.values()) {
                    mapForStage.put(herostagecost.getCondition(), herostagecost.getId());
                    arraryListForStage.add(herostagecost.getCondition());
                }
            }

            HashMap<Integer, JSONObject> map = new HashMap<>();//key:等级  value:星级和id
            ArrayList<Integer> herolvupList = new ArrayList<>();
            for (Entry<Integer, Integer> entry : map_heroadvanceddata.entrySet()) {
                Integer startTop = entry.getKey();
                Integer id = entry.getValue();

                for (int y = 0; y <= startTop; y++) {
                    heroadvanced data = DataCenter.getData(String.format("%d_%d", id, y), heroadvanced.class);
                    if (data == null) continue;
                    int starlv = data.getStarlv();
                    int herolvup = data.getHerolvup();
                    JSONObject jsonObject = new JSONObject();
                    jsonObject.put("id", id);
                    jsonObject.put("starlv", starlv);
                    map.put(herolvup, jsonObject);
                    herolvupList.add(herolvup);
                }
            }

            //从低到高排序
            Collections.sort(herolvupList);
            Collections.sort(arraryListForStage);
            //遍历计算当前星级和阶级
            for (int z = 0; z < herolvupList.size(); z++) {
                //如果都不满足就按最大星去给
                if (level >= herolvupList.get(herolvupList.size() - 1)) {
                    star = map.get(herolvupList.get(herolvupList.size() - 1)).getInteger("starlv");
                    stage = getStage(level, mapForStage, arraryListForStage);
                    heroid = map.get(herolvupList.get(herolvupList.size() - 1)).getInteger("id");
                    break;
                }
                //否则找相应的星级阶级
                if (level < herolvupList.get(z)) {
                    star = map.get(herolvupList.get(z)).getInteger("starlv");
                    stage = getStage(level, mapForStage, arraryListForStage);
                    heroid = map.get(herolvupList.get(z)).getInteger("id");
                    break;
                }

            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        returnMap.put("heroid", heroid);
        returnMap.put("stage", finalStage == 0 ? stage : finalStage);
        returnMap.put("star", finalStar == 0 ? star : finalStar);
        return returnMap;
    }


    //获取阶级 mapForStage key为等级 value为阶级
    public static Integer getStage(int level, HashMap<Integer, Integer> mapForStage, ArrayList<Integer> arraryListForStage) {
        try {
            for (int i = arraryListForStage.size() - 1; i > 0; i--) {
                if (level > arraryListForStage.get(i)) {
                    return mapForStage.get(arraryListForStage.get(i));
                }

            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return 0;
    }


    //计算敌方的属性
    public static PropertyData getOppositePropertyData(int heroId, int level, int stage, int star, int anger) {
        battleLogger(1, "征战敌方 heroId::::" + heroId + "::::stage::::" + stage + "::::star::::" + star + "::::level::::" + level);
        if (star == 0)
            battleLogger(1, "--------------------------------------------------------heroadvanceddata 找不到该武将 heroId::::" + heroId + "::::stage::::" + stage + "--------------------------------------------------------");
        herodata _herodata = DataCenter.getData(heroId, herodata.class);
        PropertyData propertyData = BattleHandle.packProperty武将基础属性(_herodata, level, stage);
        BattleHandle battleHandle = new BattleHandle();
        //!!!第二步：以下先进行额外计算
        PropertyData propertyDataAdd = new PropertyData();
        propertyDataAdd.addAllValue(battleHandle.packProperty升星属性敌方(_herodata, star));
        battleLogger(1, "升星-攻击：" + propertyDataAdd.getValue(PropertyType.P_攻击) + "物防：" + propertyDataAdd.getValue(PropertyType.P_防御) + "法防：" + propertyDataAdd.getValue(PropertyType.P_法防) + "生命:" + propertyDataAdd.getValue(PropertyType.P_生命) + "攻击增幅：" + propertyDataAdd.getValue(PropertyType.P_攻击增幅) + "防御增幅：" + propertyDataAdd.getValue(PropertyType.P_防御增幅) + "法防增幅：" + propertyDataAdd.getValue(PropertyType.P_法防增幅) + "生命增幅：" + propertyDataAdd.getValue(PropertyType.P_生命增幅));
        //!!!第三步 计算基于基础属性的增幅
        propertyData.addAllValue(battleHandle.packProperty属性增幅(propertyData, propertyDataAdd));
        battleLogger(1, "加各种增幅后-攻击：" + propertyData.getValue(PropertyType.P_攻击) + "物防：" + propertyData.getValue(PropertyType.P_防御) + "法防：" + propertyData.getValue(PropertyType.P_法防) + "生命:" + propertyData.getValue(PropertyType.P_生命));
        return propertyData;
    }


    public static PropertyData packProperty升星属性敌方(herodata _herodata, int star) {
        int heroId = _herodata.getId();
        heroadvanced _heroadvanced = DataCenter.getData(String.format("%d_%d", heroId, star), heroadvanced.class);
        PropertyData propertyData = new PropertyData();
        if (_heroadvanced == null) {
            return propertyData;
        }
        //怪物根据星级削弱属性
        PropertyData data = getHeroStarPropertyData(_heroadvanced);
        PropertyData finallPropertryDate = changPropertryDateForStar(data, star);
        propertyData.addAllValue(finallPropertryDate);
        return propertyData;
    }

    //怪物根据星级削弱属性
    private static PropertyData changPropertryDateForStar(PropertyData data, int star) {
        data.addValue(PropertyType.P_攻击增幅, -星级对应的怪物属性削减百分比[star]);
        data.addValue(PropertyType.P_生命增幅, -星级对应的怪物属性削减百分比[star]);
        data.addValue(PropertyType.P_防御增幅, -星级对应的怪物属性削减百分比[star]);
        data.addValue(PropertyType.P_法防增幅, -星级对应的怪物属性削减百分比[star]);
        return data;
    }


    //2022.4.14 征战地图,爬塔，以及任务重置
    public void changeMap(String playerCode, PlayerBean playerBean) {
        String isReset = MapReset.get(playerCode);
        if (StringUtils.isEmpty(isReset)) {
            Battle.battleLogger(1, "--------------兼容处理:重置关卡和任务奖励---------------");
            ArrayList<Integer> integers = new ArrayList<>();
            integers.add(1);
            //征战
            ConquestModule conquestModule = ConquestModule.get(playerCode);
            if (conquestModule.getMapId() >= 50) {
                conquestModule.setMapId(50);

                conquestModule.setLevelReward(integers);
            }
            conquestModule.set();

            //爬塔
            TowerModule towerModule = TowerModule.get(playerCode);
            if (towerModule.getFloor() >= 50) {
                towerModule.setFloor(50);
                towerModule.setLevelReward(integers);
            }
            towerModule.set();

            //千里单骑重置
            SoloRideModule.removeAllFromRedis(playerCode);
            SoloRideModule.deleteFromTable(playerCode);

            MapReset.set(playerCode, "1");
        }
        changeLevel(playerCode, playerBean);

        resetConquestMap(playerCode);
    }


    //2022.5.7 征战关卡记录调整：
    //1.高于100关的时候重置为100关。终生一次
    private void resetConquestMap(String playerCode) {
        String isReset = MapReset.get(playerCode);
        if (StringUtils.isNotEmpty(isReset) && (isReset.equals("2") || isReset.equals("3"))) {
            Battle.battleLogger(1, "--------------兼容处理:高于100关的时候重置为100关。终生一次---------------");
            ConquestModule conquestModule = ConquestModule.get(playerCode);
            int mapId = conquestModule.getMapId();
            ArrayList<Integer> levelReward = conquestModule.getLevelReward();

            if (mapId > 100) mapId = 100;

            Iterator<Integer> iterator = levelReward.iterator();
            while (iterator.hasNext()) {
                if (iterator.next() >= mapId) iterator.remove();
            }

            conquestModule.setMapId(mapId);
            conquestModule.setLevelReward(levelReward);
            conquestModule.set();
            MapReset.set(playerCode, "4");
        }

    }

    //2022.5.4 征战等级限制改动，相应提高玩家的等级
    public void changeLevel(String playerCode, PlayerBean playerBean) {
        String isReset = MapReset.get(playerCode);
        if (StringUtils.isNotEmpty(isReset) && isReset.equals("1")) {
            Battle.battleLogger(1, "--------------兼容处理:征战等级限制改动，相应提高玩家的等级---------------");

            ConquestModule conquestModule = ConquestModule.get(playerCode);
            int mapId = conquestModule.getMapId();
            map data = DataCenter.getData(mapId, map.class);
            int condition = data.getCondition();

            int level = playerBean.getLevel();

            if (level <= condition) {
                playerBean.setLevel(condition + 1);
                playerBean.set();
            }

            MapReset.set(playerCode, "2");
        }
    }


    //2022.4.15 battle清除
    public void cleanBattle(String playerCode) {
        try {
            String isBattleClear = BattleClear.get(playerCode);
            if (StringUtils.isEmpty(isBattleClear) || isBattleClear.equals("1")) {
                Battle.battleLogger(1, "--------------兼容处理:清除battle记录---------------");
                BattleModule.removeAllFromRedis(playerCode, BattleType.CONQ.name());
                BattleModule.removeAllFromRedis(playerCode, BattleType.TOWER.name());
                BattleClear.set(playerCode, "2");
            }
        } catch (RedisException e) {
            e.printStackTrace();
        }
    }


    //计算战力并保存缓存
    public static Long calculatePower(String playerCode, Hero hero, Format format) {
        PropertyData propertyData = packProperty(playerCode, hero, format);
        long power = BattleFomula.战力(propertyData, hero.getDataId());

        //保存缓存
        JSONObject propertyJson = (JSONObject) JSONObject.toJSON(PropertyModule.create(propertyData));
        hero.setPropertyModule(propertyJson);
        hero.setPower(power);
        Hero.set(playerCode, hero);
        //队伍的缓存更新，阵容界面需要重新计算战力
        Format format1 = Format.get(playerCode, FormatType.普通);
        format1.setIsAfreshPower(0);
        Format.set(playerCode, FormatType.普通, format1);
        return power;
    }


    //GM后台用的  去掉线程池
    public static Long calculatePowerForGm(String playerCode, Hero hero, Format format) {
        PropertyData propertyData = packProperty(playerCode, hero, format);
        long power = BattleFomula.战力(propertyData, hero.getDataId());

        //保存缓存
        JSONObject propertyJson = (JSONObject) JSONObject.toJSON(PropertyModule.create(propertyData));
        hero.setPropertyModule(propertyJson);
        hero.setPower(power);
        Hero.set2(playerCode, hero);
        //队伍的缓存更新，阵容界面需要重新计算战力
        Format format1 = Format.get(playerCode, FormatType.普通);
        format1.setIsAfreshPower(0);
        Format.set(playerCode, FormatType.普通, format1);
        return power;
    }


}
